home *** CD-ROM | disk | FTP | other *** search
/ Delphi Developer's Kit 1996 / Delphi Developer's Kit 1996.iso / power / wfc007.000 / src / serial.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-22  |  9.1 KB  |  383 lines

  1. #include <wfc.h>
  2. #pragma hdrstop
  3.  
  4. /*
  5. ** Author: Samuel R. Blackburn
  6. ** CI$: 76300,326
  7. ** Internet: sammy@sed.csc.com
  8. **
  9. ** You can use it any way you like.
  10. */
  11.  
  12. #if defined( _DEBUG )
  13. #undef THIS_FILE
  14. static char BASED_CODE THIS_FILE[] = __FILE__;
  15. #endif
  16.  
  17. IMPLEMENT_SERIAL( CSerialFile, CDummyFile, 1 )
  18.  
  19. CSerialFile::CSerialFile()
  20. {
  21.    ::ZeroMemory( &m_CommunicationsStatus, sizeof( m_CommunicationsStatus ) );
  22.    m_IsOpen = FALSE;
  23.    Name.Empty();
  24. }
  25.  
  26. CSerialFile::~CSerialFile()
  27. {
  28.    Close();
  29. }
  30.  
  31. void CSerialFile::Close( void )
  32. {
  33.    TRACE1( "CSerialFile::Close( \"%s\" )\n", (LPCTSTR) Name );
  34.  
  35.    if ( FileHandle == INVALID_HANDLE_VALUE )
  36.    {
  37.       m_IsOpen = FALSE;
  38.       return;
  39.    }
  40.  
  41.    m_ClearError( __LINE__ );
  42.  
  43.    ::EscapeCommFunction( FileHandle, CLRDTR );
  44.  
  45.    ::PurgeComm( FileHandle, PURGE_TXABORT |
  46.                             PURGE_RXABORT |
  47.                             PURGE_TXCLEAR |
  48.                             PURGE_RXCLEAR );
  49.  
  50.    CDummyFile::Close();
  51.    FileHandle = INVALID_HANDLE_VALUE;
  52.    m_IsOpen   = FALSE;
  53. }
  54.  
  55. void CSerialFile::m_ClearError( int line_number )
  56. {
  57.    if ( FileHandle == INVALID_HANDLE_VALUE )
  58.    {
  59.       return;
  60.    }
  61.  
  62.    if ( ::ClearCommError( FileHandle, &m_CommunicationErrorCodes, &m_CommunicationsStatus ) == FALSE )
  63.    {
  64.       m_ErrorCode = ::GetLastError();
  65.  
  66.       if ( m_ErrorCode == ERROR_INVALID_HANDLE )
  67.       {
  68.          FileHandle = INVALID_HANDLE_VALUE;
  69.       }
  70.  
  71.       return;
  72.    }
  73.  
  74.    if ( m_CommunicationErrorCodes != 0 )
  75.    {
  76.       TCHAR error_message[ 2048 ];
  77.  
  78.       ::ZeroMemory( error_message, sizeof( error_message ) );
  79.  
  80.       if ( m_CommunicationErrorCodes & CE_BREAK )
  81.       {
  82.          ::strcat( error_message, "\r\nThe hardware detected a break condition. (CE_BREAK);" );
  83.       }
  84.  
  85.       if ( m_CommunicationErrorCodes & CE_FRAME )
  86.       {
  87.          ::strcat( error_message, "\r\nThe hardware detected a framing error. (CE_FRAME);" );
  88.          ::PurgeComm( FileHandle, PURGE_RXCLEAR );
  89.       }
  90.  
  91.       if ( m_CommunicationErrorCodes & CE_IOE )
  92.       {
  93.          ::strcat( error_message, "\r\nAn I/O error occurred during communications with the device. (CE_IOE);" );
  94.       }
  95.  
  96.       if ( m_CommunicationErrorCodes & CE_MODE )
  97.       {
  98.          ::strcat( error_message, "\r\nThe requested mode is not supported or the hCommDev parameter is invalid. (CE_MODE);" );
  99.       }
  100.  
  101.       if ( m_CommunicationErrorCodes & CE_OVERRUN )
  102.       {
  103.          ::strcat( error_message, "\r\nA character-buffer overrun has occurred. The next character is lost. (CE_OVERRUN);" );
  104.       }
  105.  
  106.       if ( m_CommunicationErrorCodes & CE_RXOVER )
  107.       {
  108.          m_ErrorCode = CE_RXOVER;
  109.          ::strcat( error_message, "\r\nAn input buffer overflow has occurred. There is either no room in the input buffer, or a character was received after the end-of-file (EOF) character. (CE_RXOVER);" );
  110.       }
  111.  
  112.       if ( m_CommunicationErrorCodes & CE_RXPARITY )
  113.       {
  114.          ::strcat( error_message, "\r\n.The hardware detected a parity error. (CE_RXPARITY);" );
  115.       }
  116.  
  117.       if ( m_CommunicationErrorCodes & CE_TXFULL )
  118.       {
  119.          ::strcat( error_message, "\r\nThe application tried to transmit a character, but the output buffer was full. (CE_TXFULL);" );
  120.       }
  121.  
  122.       if ( m_CommunicationErrorCodes & CE_DNS )
  123.       {
  124.          ::strcat( error_message, "\r\nThe parallel device is not selected. (CE_DNS);" );
  125.       }
  126.  
  127.       if ( m_CommunicationErrorCodes & CE_PTO )
  128.       {
  129.          ::strcat( error_message, "\r\nA time-out occurred on the parallel device. (CE_PTO);" );
  130.       }
  131.  
  132.       if ( m_CommunicationErrorCodes & CE_OOP )
  133.       {
  134.          ::strcat( error_message, "\r\nThe parallel device signaled that it is out of paper. (CE_OOP);" );
  135.       }
  136.  
  137.       TCHAR temp_string[ 100 ];
  138.  
  139.       ::sprintf( temp_string, "%d (%d in input_queue)", line_number, m_CommunicationsStatus.cbInQue );
  140.  
  141.       TRACE1( "%s", error_message );
  142.       TRACE1( "%s\n", temp_string );
  143.    }
  144. }
  145.  
  146. BOOL CSerialFile::IsDataWaiting( void )
  147. {
  148.    m_ClearError( __LINE__ );
  149.  
  150.    if ( m_CommunicationsStatus.cbInQue > 0 )
  151.    {
  152.       return( TRUE );
  153.    }
  154.    else
  155.    {
  156.       return( FALSE );
  157.    }
  158. }
  159.  
  160. #pragma warning( disable : 4100 )
  161.  
  162. BOOL CSerialFile::Open( LPCTSTR channel_name, UINT open_flags, CFileException *exception_p )
  163. {
  164.    ASSERT( channel_name != NULL );
  165.  
  166.    if ( channel_name == NULL )
  167.    {
  168.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  169.       return( FALSE );
  170.    }
  171.  
  172.    Name = channel_name;
  173.  
  174.    return( Open() );
  175. }
  176.  
  177. #pragma warning( default : 4100 )
  178.  
  179. BOOL CSerialFile::Open( void )
  180. {
  181.    CString com_port_name( "" );
  182.  
  183.    int index = 0;
  184.    int string_length = Name.GetLength();
  185.  
  186.    while( index < string_length && Name[ index ] != ':' )
  187.    {
  188.       com_port_name += Name[ index ];
  189.       index++;
  190.    }
  191.  
  192.    com_port_name += ':';
  193.  
  194.    CString settings_string( "" );
  195.  
  196.    settings_string = Name.Right( ( string_length - index ) - 1 );
  197.  
  198.    FileHandle = ::CreateFile( (LPCTSTR) com_port_name,
  199.                               GENERIC_READ | GENERIC_WRITE,
  200.                               0,
  201.                               NULL,
  202.                               OPEN_EXISTING,
  203.                               FILE_ATTRIBUTE_NORMAL,
  204.                               NULL );
  205.  
  206.    if ( FileHandle == INVALID_HANDLE_VALUE )
  207.    {
  208.       m_ErrorCode = ::GetLastError();
  209.  
  210.       TRACE1( "CSerialFile::Open(), %d\n", __LINE__ );
  211.       return( FALSE );
  212.    }
  213.  
  214.    if ( ::PurgeComm( FileHandle, PURGE_TXABORT |
  215.                                  PURGE_RXABORT |
  216.                                  PURGE_TXCLEAR |
  217.                                  PURGE_RXCLEAR ) != TRUE )
  218.    {
  219.    }
  220.  
  221.    m_hFile = (HFILE) FileHandle;
  222.  
  223.    CString baud_string( "" );
  224.  
  225.    index = 0;
  226.    string_length = settings_string.GetLength();
  227.  
  228.    while( index < string_length && settings_string[ index ] != ',' )
  229.    {
  230.       baud_string += settings_string[ index ];
  231.       index++;
  232.    }
  233.  
  234.    index++; // Skip over the comma
  235.  
  236.    CString parity_string( "" );
  237.  
  238.    while( index < string_length && settings_string[ index ] != ',' )
  239.    {
  240.       parity_string += settings_string[ index ];
  241.       index++;
  242.    }
  243.  
  244.    index++; // skip the comma
  245.  
  246.    CString data_bits_string( "" );
  247.  
  248.    while( index < string_length && settings_string[ index ] != ',' )
  249.    {
  250.       data_bits_string += settings_string[ index ];
  251.       index++;
  252.    }
  253.  
  254.    index++; // another dang comma
  255.  
  256.    CString stop_bits_string( "" );
  257.  
  258.    while( index < string_length )
  259.    {
  260.       stop_bits_string += settings_string[ index ];
  261.       index++;
  262.    }
  263.  
  264.    CString dcb_string( "" );
  265.  
  266.    dcb_string  = com_port_name;
  267.    dcb_string += " baud=";
  268.    dcb_string += baud_string;
  269.    dcb_string += " parity=";
  270.    dcb_string += parity_string;
  271.    dcb_string += " data=";
  272.    dcb_string += data_bits_string;
  273.    dcb_string += " stop=";
  274.    dcb_string += stop_bits_string;
  275.  
  276.    CDeviceControlBlock device_control_block;
  277.  
  278.    if ( ::GetCommState( FileHandle, &device_control_block ) == FALSE )
  279.    {
  280.       m_ErrorCode = ::GetLastError();
  281.       TRACE1( "CSerialFile::Open() %d\n", __LINE__ );
  282.       Close();
  283.       return( FALSE );
  284.    }
  285.  
  286.    if ( ::BuildCommDCB( dcb_string, &device_control_block ) == FALSE )
  287.    {
  288.       m_ErrorCode = ::GetLastError();
  289.       TRACE1( "CSerialFile::Open() %d\n", __LINE__ );
  290.       Close();
  291.       return( FALSE );
  292.    }
  293.  
  294.    device_control_block.fAbortOnError = FALSE; // Terminate Reads & Writes if there's an error
  295.    device_control_block.fErrorChar    = TRUE;  // Replace any garbled bytes with ErrorChar
  296.    device_control_block.ErrorChar     = ' ';   // Garbage bytes are spaces
  297.    device_control_block.fBinary       = TRUE;  // Ignore EOF
  298.  
  299.    if ( ::SetCommState( FileHandle, &device_control_block ) == FALSE )
  300.    {
  301.       m_ErrorCode = ::GetLastError();
  302.       TRACE1( "CSerialFile::Open() %d\n", __LINE__ );
  303.       Close();
  304.       return( FALSE );
  305.    }
  306.  
  307.    if ( ::SetupComm( FileHandle, 4096, 1024 ) != TRUE )
  308.    {
  309.    }
  310.  
  311.    // assert DTR
  312.  
  313.    if ( ::EscapeCommFunction( FileHandle, SETDTR ) != TRUE )
  314.    {
  315.    }
  316.  
  317.    return( TRUE );
  318. }
  319.  
  320. void CSerialFile::Serialize( CArchive& archive )
  321. {
  322.    CDummyFile::Serialize( archive );
  323.  
  324.    if ( archive.IsStoring() )
  325.    {
  326.       archive << (DWORD) m_IsOpen;
  327.       archive << Name;
  328.    }
  329.    else
  330.    {
  331.       DWORD temp_dword = 0;
  332.  
  333.       archive >> temp_dword;
  334.       archive >> Name;
  335.  
  336.       m_IsOpen = temp_dword;
  337.  
  338.       if ( m_IsOpen == TRUE )
  339.       {
  340.          Open();
  341.       }
  342.    }
  343. }
  344.  
  345. UINT CSerialFile::Read( void *buffer, UINT length )
  346. {
  347.    ASSERT( buffer != NULL );
  348.  
  349.    if ( buffer == NULL )
  350.    {
  351.       return( 0 );
  352.    }
  353.  
  354.    m_ClearError( __LINE__ );
  355.  
  356.    return( CDummyFile::Read( buffer, length ) );
  357. }
  358.  
  359. void CSerialFile::Write( const void *buffer, UINT length )
  360. {
  361.    ASSERT( buffer != NULL );
  362.  
  363.    if ( buffer == NULL )
  364.    {
  365.       return;
  366.    }
  367.  
  368.    m_ClearError( __LINE__ );
  369.  
  370.    CDummyFile::Write( buffer, length );
  371. }
  372.  
  373. void CSerialFile::Write( CString& string_to_write )
  374. {
  375.    LPTSTR buffer_p = string_to_write.GetBuffer( 1 );
  376.  
  377.    UINT number_of_bytes = string_to_write.GetLength();
  378.  
  379.    Write( buffer_p, number_of_bytes );
  380.  
  381.    string_to_write.ReleaseBuffer();
  382. }
  383.